package kGeom;

public class kElementBuffer {

	protected kElement[]	elements;
	protected kRange		range;
	
	public kElementBuffer() {
		elements = new kElement[0];
		initElementRange();
	}

	/*
	 * PUBLIC METHODS
	 */

	public void append(kElement e) {
		// expand element array
		kElement[] tempElements = new kElement[elements.length + 1];
		for (int n = 0; n < elements.length; n++) {
			tempElements[n] = elements[n];
		}
		tempElements[elements.length] = e;
		elements = tempElements;

		addElementToRange(e);
	}

	public void append(kElement[] eArr) {
		// expand element array
		int valLength = 0;
		for (int n = 0; n < eArr.length; n++) if (eArr[n] != null) valLength++;
		
		int m = 0;
		kElement[] tempElements = new kElement[elements.length + valLength];
		for (int n = 0; n < elements.length; n++) {
			tempElements[m] = elements[n];
			m++;
		}
		for (int n = 0; n < eArr.length; n++) {
			if (eArr[n] != null){
			tempElements[m] = eArr[n];
			addElementToRange(eArr[n]);
			m++;
			}
		}
		elements = tempElements;
	}
	
	public void append(kElementBuffer buff){
		this.append(buff.getElements());
	}

	public void removeAt(int index) {
		if ((index >= elements.length) || (index < 0)) {
			System.out.println("warning: kSpace.removeAt() index out of range: i=" + index + ", elements.length=" + elements.length);
		}

		// contract element array
		kElement[] tempElements = new kElement[elements.length - 1];
		int m = 0;
		for (int n = 0; n < elements.length; n++) {
			if (n != index) {
				tempElements[m] = elements[n];
				m++;
			}
		}
		elements = tempElements;

		// update elementRange
		initElementRange();
	}

	public void clear() {
		elements = new kElement[0];
		range = new kRange();
	}

	public kElement[] getElements() {
		return elements;
	}
	public kElement getElement(int index) {
		if ((index >= elements.length) || (index < 0)) {
			System.out.println("warning: kSpace.getElement() index out of range: i=" + index + ", elements.length=" + elements.length);
			return kElement.invalidElement();
		}
		return elements[index];
	}
	public int length() {
		return elements.length;
	}
	public kRange getRange() {
		return range;
	}

	/**
	 * NOT FULLY IMPLIMENTED removes invalid elements from the space
	 */
	/*
	public void removeInvalidElements(float fuzz) {
		ArrayList invalidIndices = new ArrayList();
		for (int n = 0; n < elements.length; n++) {
			if (!elements[n].isValid) invalidIndices.add(Integer.valueOf(n));
			else {
				// TODO: check for tiny lines
				
				if (elements[n].getClass() == kLine.class) {
					kLine line = (kLine) elements[n];
					if (line.length() < fuzz) invalidIndices.add(Integer.valueOf(n));
				}
				
			}
		}

		for (Iterator it = invalidIndices.iterator(); it.hasNext();) {
			Integer n = (Integer) it.next();
			removeAt(n.intValue());
		}
	}
	*/

	/*
	 * PRIVATE METHODS - ELEMENT MANAGMENT
	 */
	private void initElementRange() {
		range = new kRange(1.0f);
		for (int n = 0; n < elements.length; n++) {
			addElementToRange(elements[n]);
		}
	}
	private void addElementToRange(kElement e) {
		// TODO: find a better way to keep this up to date with geom types
		Class c = e.getClass();
		if (c == kVec.class) {
			kVec t = (kVec) e;
			range.expandToPoint(t);
		} else if (c == kPointCloud.class) {
			kPointCloud pc = (kPointCloud) e;
			range.combineWith( pc.getRange() );
			
		} else if (c == kLine.class) {
			kLine line = (kLine) e;
			range.expandToPoint(line.eval(0));
			range.expandToPoint(line.eval(1));
		} else if ( (c == kRange.class) || (c == kVecField.class) ) {

		}
	}

}
